<?php

namespace Application;

use System\InitSystem;
use System\library\Benchmark;
use System\library\Debugger;
use System\library\Logger;
use System\library\loader\ClassLoader;
use System\library\config\Config;
use System\library\loader\JavascriptLoader;
use System\library\loader\CssLoader;
use System\library\logger\Formater;
use System\library\logger\writers\Display;
use System\library\logger\writers\File;
use System\library\mvc\controller\Dispatcher;
use System\library\pattern\Singleton;
use System\library\safety\Safety;
use System\library\utility\Tools;
use System\library\utility\Validate;

/**
 * <b>Class</b> :        InitApplication<br>
 * <b>Fonction</b> :     Permet l'initialisation et le démarrage de l'application mvc
 * <br>
 * @version              1.0
 * @author               Dread <dreadlokeur@gmail.com>
 * @license              Licence publique générale GNU http://www.gnu.org/licenses/gpl.html
 * @copyright            Copyright 2011 - MidichloriansPHP and contributors
 * @package              MidichloriansPHP
 *
 * @see System\library\pattern\Singleton
 */
class InitApplication extends Singleton {

    /**
     * Status de l'initialisation
     *
     * @access private
     * @static
     * @var bool
     */
    private static $_initialized = false;
    /**
     * Status du démarrage
     *
     * @access private
     * @static
     * @var bool
     */
    private $_isStarted = false;

    /**
     * Permet d'obtenir le status de l'initialisation de d'application
     *
     * @access public
     * @param void
     * @return bool attribut $_initialized (le status)
     */
    public static function isInitialized() {
        return self::$_initialized;
    }

    /**
     * Permet l'initialisation de l'application, chargements et cache des fichiers Javascript et Css, de la configuration
     *
     * @access public
     * @param void
     * @return void
     */
    public function init() {
        if (self::isInitialized())
            throw new \Exception('Application déjà initilialisée');
        $this->_loadConfig();
        $this->_loadJs();
        $this->_loadCss();
        $this->_loggerSetting();
        // Ajout des namespace Controllers et Models pour le loader de classes
        ClassLoader::addNamespacePath('Controllers', Config::getCons('PATH_CONTROLLER'));
        ClassLoader::addNamespacePath('Models', Config::getCons('PATH_MODEL'));
        Logger::getInstance()->debug('Application initilialisée');
        self::$_initialized = true;
    }

    /**
     * Permet le démarrage de l'application, dispatch des controllers, et leurs mise en marche (controller instance...)
     *
     * @access public
     * @param bool $safe sécurise l'application
     * @return void
     */
    public function start($safe = true) {
        if (!self::isInitialized())
            $this->init();
        if ($this->_isStarted)
            throw new \Exception('Application déjà démarré');

        // Config, verifie et demarre le Dispatcher de controller
        $dispatcher = Dispatcher::getInstance();
        if (file_exists(Config::getCons('PATH_CONFIG') . 'controllerDispatcher.xml'))
            $dispatcher->setDispatcherConfigFile(Config::getCons('PATH_CONFIG') . 'controllerDispatcher.xml');
        $dispatcher->setControllersDir(Config::getCons('PATH_CONTROLLER'));
        if (Config::isDefinedCons('MAINTENANCE') && Config::getCons('MAINTENANCE')) {
            $dispatcher->showMaintenance();
            exit;
        }
        $dispatcher->run();

        // On sécurise l'application ;)
        if ($safe)
            $this->_safe();

        Logger::getInstance()->debug('Application démarré');
        $this->_isStarted = true;
    }

    /**
     * Constructor, verifie que le system est initialisé
     *
     * @access protected
     * @param void
     * @return void
     */
    protected function __construct() {
        if (!InitSystem::isInitialized())
            throw new \Exception('Le system doit être initialisé avant d\'initilisaté l\'application');
    }

    /**
     * Charge la configuration de la config, include du fichier config.php et autoload des fichiers ini dans le path application/config
     *
     * @access protected
     * @param void
     * @return void
     */
    private function _loadConfig() {
        if (file_exists(Config::getCons('PATH_APPLICATION') . 'config' . DIRECTORY_SEPARATOR . 'config.php'))
            require_once Config::getCons('PATH_APPLICATION') . 'config' . DIRECTORY_SEPARATOR . 'config.php';

        foreach (Tools::cleanScandir(Config::getCons('PATH_APPLICATION') . 'config' . DIRECTORY_SEPARATOR . 'autoload') as $file) {
            if (Validate::isFileType('ini', $file))
                Config::loadIniFile(Config::getCons('PATH_APPLICATION') . 'config' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $file);
        }
    }

    /**
     * Auto-Chargement des fichiers javascript contenu dans le path ressources de l'app, + compression et mise en cache d'un javascript global
     *
     * @access private
     * @param void
     * @return void
     */
    private function _loadJs() {
        $js = new JavascriptLoader();
        $js->setCompressed(true)->setCached(true)->setCacheDir(Config::getCons('PATH_CACHE') . 'javascript' . DIRECTORY_SEPARATOR);

        // Compresse
        foreach (Tools::cleanScandir(Config::getCons('PATH_JS')) as $value) {
            if (Validate::isFileType('js', $value))
                $js->addFile(Config::getCons('PATH_JS') . $value, false);
        }
        // No-compresse)
        foreach (Tools::cleanScandir(Config::getCons('PATH_JS') . 'no-compresse' . DIRECTORY_SEPARATOR) as $value) {
            if (Validate::isFileType('js', $value))
                $js->addFile(Config::getCons('PATH_JS') . 'no-compresse' . DIRECTORY_SEPARATOR . $value, true);
        }
        $js->output();
    }

    /**
     * Auto-Chargement des fichiers css contenu dans le path ressources de l'app, et mise en cache d'un css global
     *
     * @access private
     * @param void
     * @return void
     */
    private function _loadCss() {
        $css = new CssLoader();
        $css->setCached(true)->setCacheDir(Config::getCons('PATH_CACHE') . 'css' . DIRECTORY_SEPARATOR);

        // On load les css
        foreach (Tools::cleanScandir(Config::getCons('PATH_CSS')) as $value) {
            if (Validate::isFileType('css', $value))
                $css->addFile(Config::getCons('PATH_CSS') . $value, false);
        }
        //Et on génére le .css de sortie
        $css->output();
    }

    /**
     * Demarre le logger, définit son formater, et ajoute ses observers en fonction du status du mode debug
     *
     * @access private
     * @param void
     * @return void
     */
    private function _loggerSetting() {
        if (InitSystem::isDebug()) {
            $logger = Logger::getInstance();
            //Ajout de writer File pour écrire les logs
            $logger->setFormater(Formater::factory(Config::getCons('LOGGER_FORMATER')));
            $logger->attach(new File(Config::getCons('PATH_LOG'), Config::getCons('LOG_FILE_NAME')));   
        }
    }

    /**
     * Safe
     *
     * @access private
     * @param void
     * @return void
     */
    private function _safe() {

    }

}

?>
